home *** CD-ROM | disk | FTP | other *** search
/ The Utilities Experience / The Utilities Experience - Volume 1.iso / software / misc / o-z / x-windows / mesa-amiwin / src / light.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-11-30  |  44.2 KB  |  1,480 lines

  1. /* light.c */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  1.2
  6.  * Copyright (C) 1995  Brian Paul  (brianp@ssec.wisc.edu)
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25. $Id: light.c,v 1.27 1995/11/02 20:03:05 brianp Exp $
  26.  
  27. $Log: light.c,v $
  28.  * Revision 1.27  1995/11/02  20:03:05  brianp
  29.  * changed some GLuints to GLints
  30.  *
  31.  * Revision 1.26  1995/11/01  23:18:47  brianp
  32.  * fixed a typo in gl_color_shade()
  33.  *
  34.  * Revision 1.25  1995/11/01  21:46:06  brianp
  35.  * optimized gl_color_shade(), added new gl_color_shade_vertices() function
  36.  *
  37.  * Revision 1.24  1995/10/24  18:36:58  brianp
  38.  * only set CC.NewState when ShadeModel really changes
  39.  *
  40.  * Revision 1.23  1995/10/14  17:41:52  brianp
  41.  * add code to compile glLightModel into display lists
  42.  *
  43.  * Revision 1.22  1995/10/06  13:02:56  brianp
  44.  * fixed glMaterial GL_AMBIENT_AND_DIFFUSE bug
  45.  *
  46.  * Revision 1.21  1995/09/26  17:20:33  brianp
  47.  * fixed uninitialized fmask,bmask bug in gl_material
  48.  *
  49.  * Revision 1.20  1995/09/25  19:24:19  brianp
  50.  * implemented per-vertex glMaterial calls
  51.  *
  52.  * Revision 1.19  1995/09/25  13:21:13  brianp
  53.  * fixed a bug in computing the specular coefficient per Olaf Flebbe
  54.  *
  55.  * Revision 1.18  1995/09/22  16:22:03  brianp
  56.  * added comment about glMaterial not working inside glBegin/glEnd
  57.  *
  58.  * Revision 1.17  1995/09/05  15:35:08  brianp
  59.  * introduced CC.NewState convention
  60.  * many small optimizations made in gl_color_shade() and gl_index_shade()
  61.  *
  62.  * Revision 1.16  1995/07/25  13:27:51  brianp
  63.  * gl_index_shade() returns GLfloats instead of GLuints
  64.  *
  65.  * Revision 1.15  1995/05/30  15:10:45  brianp
  66.  * use ROUND() macro in glGetMaterialiv
  67.  *
  68.  * Revision 1.14  1995/05/29  21:21:53  brianp
  69.  * added glGetMaterial*() functions
  70.  *
  71.  * Revision 1.13  1995/05/22  21:02:41  brianp
  72.  * Release 1.2
  73.  *
  74.  * Revision 1.12  1995/05/12  17:00:43  brianp
  75.  * changed CC.Mode!=0 to INSIDE_BEGIN_END
  76.  *
  77.  * Revision 1.11  1995/05/12  16:29:51  brianp
  78.  * fixed glGetLightiv()'s prototype
  79.  *
  80.  * Revision 1.10  1995/04/13  19:48:33  brianp
  81.  * fixed GL_LIGHT_MODEL_LOCAL_VIEWER bugs per Armin Liebchen
  82.  *
  83.  * Revision 1.9  1995/04/08  15:25:45  brianp
  84.  * compile glShadeModel
  85.  * fixed pow() domain error
  86.  * added spotlight and attenutation factor to gl_index_shade
  87.  *
  88.  * Revision 1.8  1995/03/28  20:28:03  brianp
  89.  * fixed alpha lighting bug
  90.  *
  91.  * Revision 1.7  1995/03/10  21:41:01  brianp
  92.  * added divide by zero checks
  93.  *
  94.  * Revision 1.6  1995/03/09  21:41:03  brianp
  95.  * new ModelViewInv matrix logic
  96.  *
  97.  * Revision 1.5  1995/03/09  20:07:08  brianp
  98.  * changed gl_transform_point to macro call
  99.  * changed order of arguments in gl_transform_vector
  100.  *
  101.  * Revision 1.4  1995/03/04  19:29:44  brianp
  102.  * 1.1 beta revision
  103.  *
  104.  * Revision 1.3  1995/02/25  21:01:56  brianp
  105.  * added underflow check for specular coefficient
  106.  *
  107.  * Revision 1.2  1995/02/25  18:52:12  brianp
  108.  * changed NORMALIZE macro
  109.  *
  110.  * Revision 1.1  1995/02/24  14:23:06  brianp
  111.  * Initial revision
  112.  *
  113.  */
  114.  
  115.  
  116. #include <assert.h>
  117. #include <math.h>
  118. #ifndef M_PI
  119. #  define M_PI (3.1415926)
  120. #endif
  121. #include "context.h"
  122. #include "list.h"
  123. #include "macros.h"
  124. #include "vb.h"
  125. #include "xform.h"
  126.  
  127.  
  128.  
  129. #define RAD2DEG (180.0/M_PI)
  130.  
  131.  
  132.  
  133.  
  134. void glShadeModel( GLenum mode )
  135. {
  136.    if (CC.CompileFlag) {
  137.       gl_save_shademodel( mode );
  138.    }
  139.    if (CC.ExecuteFlag) {
  140.       if (INSIDE_BEGIN_END) {
  141.      gl_error( GL_INVALID_OPERATION, "glShadeModel" );
  142.      return;
  143.       }
  144.  
  145.       switch (mode) {
  146.      case GL_FLAT:
  147.      case GL_SMOOTH:
  148.             if (CC.Light.ShadeModel!=mode) {
  149.                CC.Light.ShadeModel = mode;
  150.                CC.NewState = GL_TRUE;
  151.             }
  152.         break;
  153.      default:
  154.         gl_error( GL_INVALID_ENUM, "glShadeModel" );
  155.       }
  156.    }
  157. }
  158.  
  159.  
  160.  
  161.  
  162. void glColorMaterial( GLenum face, GLenum mode )
  163. {
  164.    if (INSIDE_BEGIN_END) {
  165.       gl_error( GL_INVALID_OPERATION, "glColorMaterial" );
  166.       return;
  167.    }
  168.  
  169.    switch (face) {
  170.       case GL_FRONT:
  171.       case GL_BACK:
  172.       case GL_FRONT_AND_BACK:
  173.          if (CC.ExecuteFlag) {
  174.         CC.Light.ColorMaterialFace = face;
  175.      }
  176.      if (CC.CompileFlag) {
  177.         gl_save_set_enum( &CC.Light.ColorMaterialFace, face );
  178.      }
  179.      break;
  180.       default:
  181.      gl_error( GL_INVALID_ENUM, "glColorMaterial" );
  182.      return;
  183.    }
  184.  
  185.    switch (mode) {
  186.       case GL_EMISSION:
  187.       case GL_AMBIENT:
  188.       case GL_DIFFUSE:
  189.       case GL_SPECULAR:
  190.       case GL_AMBIENT_AND_DIFFUSE:
  191.          if (CC.ExecuteFlag) {
  192.         CC.Light.ColorMaterialMode = mode;
  193.      }
  194.      if (CC.CompileFlag) {
  195.         gl_save_set_enum( &CC.Light.ColorMaterialMode, mode );
  196.      }
  197.      break;
  198.       default:
  199.      gl_error( GL_INVALID_ENUM, "glColorMaterial" );
  200.      return;
  201.    }
  202. }
  203.  
  204.  
  205.  
  206.  
  207. /*
  208.  * pname: GL_AMBIENT, red, green, blue, alpha in [-1,1]
  209.  *        GL_DIFFUSE, red, green, blue, alhpa in [-1,1]
  210.  *        GL_SPECULAR, red, green, blue, alpha in [-1,1]
  211.  *        GL_POSITION, x, y, z, w in homogeneous object coordinates
  212.  *        GL_SPOT_DIRECTION, dx, dy, dz
  213.  *        GL_SPOT_EXPONENT, intensity in [0,128]
  214.  *        GL_SPOT_CUTOFF, angle in [0,90] or 180
  215.  *        GL_CONSTANT_ATTENUATION, factor >= 0
  216.  *        GL_LINEAR_ATTENUATION, factor >= 0
  217.  *        GL_QUADRATIC_ATTENUATION, factor >= 0
  218.  */
  219. void gl_light( GLenum light, GLenum pname, const GLfloat *params )
  220. {
  221.    GLint l;
  222.  
  223.    if (INSIDE_BEGIN_END) {
  224.       gl_error( GL_INVALID_OPERATION, "glShadeModel" );
  225.       return;
  226.    }
  227.  
  228.    l = (GLint) (light - GL_LIGHT0);
  229.  
  230.    if (l<0 || l>=MAX_LIGHTS) {
  231.       gl_error( GL_INVALID_ENUM, "glLight" );
  232.       return;
  233.    }
  234.  
  235.    switch (pname) {
  236.       case GL_AMBIENT:
  237.          COPY_4V( CC.Light.Light[l].Ambient, params );
  238.          break;
  239.       case GL_DIFFUSE:
  240.          COPY_4V( CC.Light.Light[l].Diffuse, params );
  241.          break;
  242.       case GL_SPECULAR:
  243.          COPY_4V( CC.Light.Light[l].Specular, params );
  244.          break;
  245.       case GL_POSITION:
  246.      /* transform position by ModelView matrix */
  247.      TRANSFORM_POINT( CC.Light.Light[l].Position, CC.ModelViewMatrix, params );
  248.          COPY_3V( CC.Light.Light[l].NormPosition, CC.Light.Light[l].Position );
  249.          NORMALIZE_3V( CC.Light.Light[l].NormPosition );
  250.          break;
  251.       case GL_SPOT_DIRECTION:
  252.      /* transform direction by inverse modelview */
  253.      if (!CC.ModelViewInvValid) {
  254.         gl_compute_modelview_inverse();
  255.      }
  256.      gl_transform_vector( CC.Light.Light[l].Direction,
  257.                   params, CC.ModelViewInv);
  258.          break;
  259.       case GL_SPOT_EXPONENT:
  260.          if (params[0]<0.0 || params[0]>128.0) {
  261.             gl_error( GL_INVALID_VALUE, "glLight" );
  262.             return;
  263.          }
  264.          CC.Light.Light[l].SpotExponent = params[0];
  265.          break;
  266.       case GL_SPOT_CUTOFF:
  267.          if ((params[0]<0.0 || params[0]>90.0) && params[0]!=180.0) {
  268.             gl_error( GL_INVALID_VALUE, "glLight" );
  269.             return;
  270.          }
  271.          CC.Light.Light[l].SpotCutoff = params[0];
  272.          break;
  273.       case GL_CONSTANT_ATTENUATION:
  274.          if (params[0]<0.0) {
  275.             gl_error( GL_INVALID_VALUE, "glLight" );
  276.             return;
  277.          }
  278.          CC.Light.Light[l].ConstantAttenuation = params[0];
  279.          break;
  280.       case GL_LINEAR_ATTENUATION:
  281.          if (params[0]<0.0) {
  282.             gl_error( GL_INVALID_VALUE, "glLight" );
  283.             return;
  284.          }
  285.          CC.Light.Light[l].LinearAttenuation = params[0];
  286.          break;
  287.       case GL_QUADRATIC_ATTENUATION:
  288.          if (params[0]<0.0) {
  289.             gl_error( GL_INVALID_VALUE, "glLight" );
  290.             return;
  291.          }
  292.          CC.Light.Light[l].QuadraticAttenuation = params[0];
  293.          break;
  294.       default:
  295.          gl_error( GL_INVALID_ENUM, "glLight" );
  296.          break;
  297.    }
  298.  
  299. }
  300.  
  301.  
  302.  
  303. /*
  304.  * light: GL_LIGHT0, GL_LIGHT1, ... GL_LIGHTn where n=GL_MAX_LIGHTS-1
  305.  * pname: GL_SPOT_EXPONENT, GL_SPOT_CUTOFF, GL_CONSTANT_ATTENUATION,
  306.  *        GL_LINEAR_ATTENUATION, GL_QUADRATIC_ATTENUATION
  307.  */
  308. void glLightf( GLenum light, GLenum pname, GLfloat param )
  309. {
  310.    if (CC.ExecuteFlag) {
  311.       gl_light( light, pname, ¶m );
  312.    }
  313.    if (CC.CompileFlag) {
  314.       gl_save_light( light, pname, ¶m, 1 );
  315.    }
  316. }
  317.  
  318.  
  319.  
  320. void glLighti( GLenum light, GLenum pname, GLint param )
  321. {
  322.    GLfloat fparam;
  323.  
  324.    fparam = (GLfloat) param;
  325.    if (CC.ExecuteFlag) {
  326.       gl_light( light, pname, &fparam );
  327.    }
  328.    if (CC.CompileFlag) {
  329.       gl_save_light( light, pname, &fparam, 1 );
  330.    }
  331. }
  332.  
  333.  
  334.  
  335. void glLightfv( GLenum light, GLenum pname, const GLfloat *params )
  336. {
  337.    if (CC.ExecuteFlag) {
  338.       gl_light( light, pname, params );
  339.    }
  340.    if (CC.CompileFlag) {
  341.       gl_save_light( light, pname, params, 4 );
  342.    }
  343. }
  344.  
  345.  
  346.  
  347. void glLightiv( GLenum light, GLenum pname, const GLint *params )
  348. {
  349.    GLfloat fparam[4];
  350.  
  351.    switch (pname) {
  352.       case GL_AMBIENT:
  353.       case GL_DIFFUSE:
  354.       case GL_SPECULAR:
  355.          fparam[0] = INT_TO_FLOAT( params[0] );
  356.          fparam[1] = INT_TO_FLOAT( params[1] );
  357.          fparam[2] = INT_TO_FLOAT( params[2] );
  358.          fparam[3] = INT_TO_FLOAT( params[3] );
  359.          break;
  360.       case GL_POSITION:
  361.          fparam[0] = (GLfloat) params[0];
  362.          fparam[1] = (GLfloat) params[1];
  363.          fparam[2] = (GLfloat) params[2];
  364.          fparam[3] = (GLfloat) params[3];
  365.          break;
  366.       case GL_SPOT_DIRECTION:
  367.          fparam[0] = (GLfloat) params[0];
  368.          fparam[1] = (GLfloat) params[1];
  369.          fparam[2] = (GLfloat) params[2];
  370.          break;
  371.       case GL_SPOT_EXPONENT:
  372.       case GL_SPOT_CUTOFF:
  373.       case GL_CONSTANT_ATTENUATION:
  374.       case GL_LINEAR_ATTENUATION:
  375.       case GL_QUADRATIC_ATTENUATION:
  376.          fparam[0] = (GLfloat) params[0];
  377.          break;
  378.       default:
  379.          gl_error( GL_INVALID_ENUM, "glLight" );
  380.          return;
  381.    }
  382.    if (CC.ExecuteFlag) {
  383.       gl_light( light, pname, fparam );
  384.    }
  385.    if (CC.CompileFlag) {
  386.       gl_save_light( light, pname, fparam, 4 );
  387.    }
  388. }
  389.  
  390.  
  391.  
  392. void glGetLightfv( GLenum light, GLenum pname, GLfloat *params )
  393. {
  394.    GLint l;
  395.  
  396.    l = (GLint) (light - GL_LIGHT0);
  397.  
  398.    if (l<0 || l>=MAX_LIGHTS) {
  399.       gl_error( GL_INVALID_ENUM, "glGetLightfv" );
  400.       return;
  401.    }
  402.  
  403.    switch (pname) {
  404.       case GL_AMBIENT:
  405.          COPY_4V( params, CC.Light.Light[l].Ambient );
  406.          break;
  407.       case GL_DIFFUSE:
  408.          COPY_4V( params, CC.Light.Light[l].Diffuse );
  409.          break;
  410.       case GL_SPECULAR:
  411.          COPY_4V( params, CC.Light.Light[l].Specular );
  412.          break;
  413.       case GL_POSITION:
  414.          COPY_4V( params, CC.Light.Light[l].Position );
  415.          break;
  416.       case GL_SPOT_DIRECTION:
  417.          COPY_3V( params, CC.Light.Light[l].Direction );
  418.          break;
  419.       case GL_SPOT_EXPONENT:
  420.          params[0] = CC.Light.Light[l].SpotExponent;
  421.          break;
  422.       case GL_SPOT_CUTOFF:
  423.          params[0] = CC.Light.Light[l].SpotCutoff;
  424.          break;
  425.       case GL_CONSTANT_ATTENUATION:
  426.          params[0] = CC.Light.Light[l].ConstantAttenuation;
  427.          break;
  428.       case GL_LINEAR_ATTENUATION:
  429.          params[0] = CC.Light.Light[l].LinearAttenuation;
  430.          break;
  431.       case GL_QUADRATIC_ATTENUATION:
  432.          params[0] = CC.Light.Light[l].QuadraticAttenuation;
  433.          break;
  434.       default:
  435.          gl_error( GL_INVALID_ENUM, "glGetLightfv" );
  436.          break;
  437.    }
  438. }
  439.  
  440.  
  441.  
  442. void glGetLightiv( GLenum light, GLenum pname, GLint *params )
  443. {
  444.    /* TODO */
  445. }
  446.  
  447.  
  448.  
  449. /**********************************************************************/
  450. /***                        Light Model                             ***/
  451. /**********************************************************************/
  452.  
  453.  
  454. void gl_lightmodel( GLenum pname, const GLfloat *params )
  455. {
  456.    switch (pname) {
  457.       case GL_LIGHT_MODEL_AMBIENT:
  458.          COPY_4V( CC.Light.Model.Ambient, params );
  459.          break;
  460.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  461.          if (params[0]==0.0)
  462.             CC.Light.Model.LocalViewer = GL_FALSE;
  463.          else
  464.             CC.Light.Model.LocalViewer = GL_TRUE;
  465.          break;
  466.       case GL_LIGHT_MODEL_TWO_SIDE:
  467.          if (params[0]==0.0)
  468.             CC.Light.Model.TwoSide = GL_FALSE;
  469.          else
  470.             CC.Light.Model.TwoSide = GL_TRUE;
  471.          CC.NewState = GL_TRUE;
  472.          break;
  473.       default:
  474.          gl_error( GL_INVALID_ENUM, "glLightModel" );
  475.          break;
  476.    }
  477. }
  478.  
  479.  
  480.  
  481. /*
  482.  * pname: GL_LIGHT_MODEL_LOCAL_VIEWER, GL_LIGHT_MODEL_TWO_SIDE
  483.  */
  484. void glLightModelf( GLenum pname, GLfloat param )
  485. {
  486.    if (CC.CompileFlag) {
  487.       gl_save_lightmodel( pname, ¶m );
  488.    }
  489.    if (CC.ExecuteFlag) {
  490.       gl_lightmodel( pname, ¶m );
  491.    }
  492. }
  493.  
  494.  
  495.  
  496. void glLightModeli( GLenum pname, GLint param )
  497. {
  498.    GLfloat fparam = (GLfloat) param;
  499.    if (CC.CompileFlag) {
  500.       gl_save_lightmodel( pname, &fparam );
  501.    }
  502.    if (CC.ExecuteFlag) {
  503.       gl_lightmodel( pname, &fparam );
  504.    }
  505. }
  506.  
  507.  
  508.  
  509. /*
  510.  * pname: GL_LIGHT_MODEL_AMBIENT red, green, blue in [1.0, -1.0]
  511.  *        GL_LIGHT_MODEL_LOCAL_VIEWER mode where 0.0 = point, else parallel
  512.  *        GL_LIGHT_MODEL_TWO_SIDE mode where 0.0 = one-sided, else 2-sided
  513.  */
  514. void glLightModelfv( GLenum pname, const GLfloat *params )
  515. {
  516.    if (CC.CompileFlag) {
  517.       gl_save_lightmodel( pname, params );
  518.    }
  519.    if (CC.ExecuteFlag) {
  520.       gl_lightmodel( pname, params );
  521.    }
  522. }
  523.  
  524.  
  525.  
  526. void glLightModeliv( GLenum pname, const GLint *params )
  527. {
  528.    GLfloat fparam[4];
  529.  
  530.    switch (pname) {
  531.       case GL_LIGHT_MODEL_AMBIENT:
  532.          fparam[0] = INT_TO_FLOAT( params[0] );
  533.          fparam[1] = INT_TO_FLOAT( params[1] );
  534.          fparam[2] = INT_TO_FLOAT( params[2] );
  535.          fparam[3] = INT_TO_FLOAT( params[3] );
  536.          break;
  537.       case GL_LIGHT_MODEL_LOCAL_VIEWER:
  538.       case GL_LIGHT_MODEL_TWO_SIDE:
  539.          fparam[0] = (GLfloat) params[0];
  540.          break;
  541.       default:
  542.          gl_error( GL_INVALID_ENUM, "glLightModeliv" );
  543.          return;
  544.    }
  545.    if (CC.CompileFlag) {
  546.       gl_save_lightmodel( pname, fparam );
  547.    }
  548.    if (CC.ExecuteFlag) {
  549.       gl_lightmodel( pname, fparam );
  550.    }
  551. }
  552.  
  553.  
  554.  
  555.  
  556. /********** MATERIAL **********/
  557.  
  558.  
  559.  
  560. void gl_material( GLenum face, GLenum pname, const GLfloat *params )
  561. {
  562.    GLuint bitmask = 0, fmask = 0, bmask = 0;
  563.    struct gl_material *mat;
  564.  
  565.    if (face!=GL_FRONT && face!=GL_BACK && face!=GL_FRONT_AND_BACK) {
  566.       gl_error( GL_INVALID_ENUM, "glMaterial" );
  567.       return;
  568.    }
  569.  
  570.    if (face==GL_FRONT || face==GL_FRONT_AND_BACK) {
  571.       fmask = 0xfff;
  572.    }
  573.    if (face==GL_BACK || face==GL_FRONT_AND_BACK) {
  574.       bmask = 0xfff;
  575.    }
  576.  
  577.    /* Make a bitmask indicating what material attribute(s) we're updating */
  578.    switch (pname) {
  579.       case GL_AMBIENT:
  580.          bitmask |= (FRONT_AMBIENT_BIT & fmask) | (BACK_AMBIENT_BIT & bmask);
  581.          break;
  582.       case GL_DIFFUSE:
  583.          bitmask |= (FRONT_DIFFUSE_BIT & fmask) | (BACK_DIFFUSE_BIT & bmask);
  584.          break;
  585.       case GL_SPECULAR:
  586.          bitmask |= (FRONT_SPECULAR_BIT & fmask) | (BACK_SPECULAR_BIT & bmask);
  587.          break;
  588.       case GL_EMISSION:
  589.          bitmask |= (FRONT_EMISSION_BIT & fmask) | (BACK_EMISSION_BIT & bmask);
  590.          break;
  591.       case GL_SHININESS:
  592.          bitmask |= (FRONT_SHININESS_BIT & fmask) | (BACK_SHININESS_BIT & bmask);
  593.          break;
  594.       case GL_AMBIENT_AND_DIFFUSE:
  595.          bitmask |= ((FRONT_AMBIENT_BIT | FRONT_DIFFUSE_BIT) & fmask)
  596.                   | ((BACK_AMBIENT_BIT | BACK_DIFFUSE_BIT) & bmask);
  597.          break;
  598.       case GL_COLOR_INDEXES:
  599.          bitmask |= (FRONT_INDEXES_BIT & fmask) | (BACK_INDEXES_BIT & bmask);
  600.          break;
  601.       default:
  602.          gl_error( GL_INVALID_ENUM, "glMaterial(pname)" );
  603.          return;
  604.    }
  605.  
  606.    if (INSIDE_BEGIN_END) {
  607.       /* Save per-vertex material changes in the Vertex Buffer.
  608.        * The update_material function will eventually update the global
  609.        * CC.Light.Material values.
  610.        */
  611.       mat = VB.Material[VB.Count];
  612.       VB.MaterialMask[VB.Count] |= bitmask;
  613.       VB.MaterialChanges = GL_TRUE;
  614.    }
  615.    else {
  616.       /* just update the global material property */
  617.       mat = CC.Light.Material;
  618.    }
  619.  
  620.    if (bitmask & FRONT_AMBIENT_BIT) {
  621.       COPY_4V( mat[0].Ambient, params );
  622.    }
  623.    if (bitmask & BACK_AMBIENT_BIT) {
  624.       COPY_4V( mat[1].Ambient, params );
  625.    }
  626.    if (bitmask & FRONT_DIFFUSE_BIT) {
  627.       COPY_4V( mat[0].Diffuse, params );
  628.    }
  629.    if (bitmask & BACK_DIFFUSE_BIT) {
  630.       COPY_4V( mat[1].Diffuse, params );
  631.    }
  632.    if (bitmask & FRONT_SPECULAR_BIT) {
  633.       COPY_4V( mat[0].Specular, params );
  634.    }
  635.    if (bitmask & BACK_SPECULAR_BIT) {
  636.       COPY_4V( mat[1].Specular, params );
  637.    }
  638.    if (bitmask & FRONT_EMISSION_BIT) {
  639.       COPY_4V( mat[0].Emission, params );
  640.    }
  641.    if (bitmask & BACK_EMISSION_BIT) {
  642.       COPY_4V( mat[1].Emission, params );
  643.    }
  644.    if (bitmask & FRONT_SHININESS_BIT) {
  645.       mat[0].Shininess = params[0];
  646.    }
  647.    if (bitmask & BACK_SHININESS_BIT) {
  648.       mat[1].Shininess = params[0];
  649.    }
  650.    if (bitmask & FRONT_INDEXES_BIT) {
  651.       mat[0].AmbientIndex = params[0];
  652.       mat[0].DiffuseIndex = params[1];
  653.       mat[0].SpecularIndex = params[2];
  654.    }
  655.    if (bitmask & BACK_INDEXES_BIT) {
  656.       mat[1].AmbientIndex = params[0];
  657.       mat[1].DiffuseIndex = params[1];
  658.       mat[1].SpecularIndex = params[2];
  659.    }
  660. }
  661.  
  662.  
  663.  
  664. void glMaterialf( GLenum face, GLenum pname, GLfloat param )
  665. {
  666.    if (CC.CompileFlag) {
  667.       gl_save_material( face, pname, ¶m );
  668.    }
  669.    if (CC.ExecuteFlag) {
  670.       gl_material( face, pname, ¶m );
  671.    }
  672. }
  673.  
  674.  
  675.  
  676. void glMateriali( GLenum face, GLenum pname, GLint param )
  677. {
  678.    GLfloat fparam;
  679.  
  680.    fparam = (GLfloat) param;
  681.  
  682.    if (CC.CompileFlag) {
  683.       gl_save_material( face, pname, &fparam );
  684.    }
  685.    if (CC.ExecuteFlag) {
  686.       gl_material( face, pname, &fparam );
  687.    }
  688. }
  689.  
  690.  
  691.  
  692. void glMaterialfv( GLenum face, GLenum pname, const GLfloat *params )
  693. {
  694.    if (CC.CompileFlag) {
  695.       gl_save_material( face, pname, params );
  696.    }
  697.    if (CC.ExecuteFlag) {
  698.       gl_material( face, pname, params );
  699.    }
  700. }
  701.  
  702.  
  703.  
  704. void glMaterialiv( GLenum face, GLenum pname, const GLint *params )
  705. {
  706.    GLfloat fparam[4];
  707.  
  708.    switch (pname) {
  709.       case GL_AMBIENT:
  710.       case GL_DIFFUSE:
  711.       case GL_SPECULAR:
  712.       case GL_EMISSION:
  713.       case GL_AMBIENT_AND_DIFFUSE:
  714.          fparam[0] = INT_TO_FLOAT( params[0] );
  715.          fparam[1] = INT_TO_FLOAT( params[1] );
  716.          fparam[2] = INT_TO_FLOAT( params[2] );
  717.          fparam[3] = INT_TO_FLOAT( params[3] );
  718.          break;
  719.       case GL_SHININESS:
  720.          fparam[0] = (GLfloat) params[0];
  721.          break;
  722.       case GL_COLOR_INDEXES:
  723.          fparam[0] = (GLfloat) params[0];
  724.          fparam[1] = (GLfloat) params[1];
  725.          fparam[2] = (GLfloat) params[2];
  726.          break;
  727.    }
  728.    if (CC.CompileFlag) {
  729.       gl_save_material( face, pname, fparam );
  730.    }
  731.    if (CC.ExecuteFlag) {
  732.       gl_material( face, pname, fparam );
  733.    }
  734. }
  735.  
  736.  
  737.  
  738. void glGetMaterialfv( GLenum face, GLenum pname, GLfloat *params )
  739. {
  740.    GLuint f;
  741.  
  742.    if (INSIDE_BEGIN_END) {
  743.       gl_error( GL_INVALID_OPERATION, "glGetMaterialfv" );
  744.       return;
  745.    }
  746.    if (face==GL_FRONT) {
  747.       f = 0;
  748.    }
  749.    else if (face==GL_BACK) {
  750.       f = 1;
  751.    }
  752.    else {
  753.       gl_error( GL_INVALID_ENUM, "glGetMaterialfv(face)" );
  754.       return;
  755.    }
  756.    switch (pname) {
  757.       case GL_AMBIENT:
  758.          COPY_4V( params, CC.Light.Material[f].Ambient );
  759.          break;
  760.       case GL_DIFFUSE:
  761.          COPY_4V( params, CC.Light.Material[f].Diffuse );
  762.      break;
  763.       case GL_SPECULAR:
  764.          COPY_4V( params, CC.Light.Material[f].Specular );
  765.      break;
  766.       case GL_EMISSION:
  767.      COPY_4V( params, CC.Light.Material[f].Emission );
  768.      break;
  769.       case GL_SHININESS:
  770.      *params = CC.Light.Material[f].Shininess;
  771.      break;
  772.       case GL_COLOR_INDEXES:
  773.      params[0] = CC.Light.Material[f].AmbientIndex;
  774.      params[1] = CC.Light.Material[f].DiffuseIndex;
  775.      params[2] = CC.Light.Material[f].SpecularIndex;
  776.      break;
  777.       default:
  778.          gl_error( GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  779.    }
  780. }
  781.  
  782.  
  783.  
  784. void glGetMaterialiv( GLenum face, GLenum pname, GLint *params )
  785. {
  786.    GLuint f;
  787.  
  788.    if (INSIDE_BEGIN_END) {
  789.       gl_error( GL_INVALID_OPERATION, "glGetMaterialiv" );
  790.       return;
  791.    }
  792.    if (face==GL_FRONT) {
  793.       f = 0;
  794.    }
  795.    else if (face==GL_BACK) {
  796.       f = 1;
  797.    }
  798.    else {
  799.       gl_error( GL_INVALID_ENUM, "glGetMaterialiv(face)" );
  800.       return;
  801.    }
  802.    switch (pname) {
  803.       case GL_AMBIENT:
  804.          params[0] = FLOAT_TO_INT( CC.Light.Material[f].Ambient[0] );
  805.          params[1] = FLOAT_TO_INT( CC.Light.Material[f].Ambient[1] );
  806.          params[2] = FLOAT_TO_INT( CC.Light.Material[f].Ambient[2] );
  807.          params[3] = FLOAT_TO_INT( CC.Light.Material[f].Ambient[3] );
  808.          break;
  809.       case GL_DIFFUSE:
  810.          params[0] = FLOAT_TO_INT( CC.Light.Material[f].Diffuse[0] );
  811.          params[1] = FLOAT_TO_INT( CC.Light.Material[f].Diffuse[1] );
  812.          params[2] = FLOAT_TO_INT( CC.Light.Material[f].Diffuse[2] );
  813.          params[3] = FLOAT_TO_INT( CC.Light.Material[f].Diffuse[3] );
  814.      break;
  815.       case GL_SPECULAR:
  816.          params[0] = FLOAT_TO_INT( CC.Light.Material[f].Specular[0] );
  817.          params[1] = FLOAT_TO_INT( CC.Light.Material[f].Specular[1] );
  818.          params[2] = FLOAT_TO_INT( CC.Light.Material[f].Specular[2] );
  819.          params[3] = FLOAT_TO_INT( CC.Light.Material[f].Specular[3] );
  820.      break;
  821.       case GL_EMISSION:
  822.          params[0] = FLOAT_TO_INT( CC.Light.Material[f].Emission[0] );
  823.          params[1] = FLOAT_TO_INT( CC.Light.Material[f].Emission[1] );
  824.          params[2] = FLOAT_TO_INT( CC.Light.Material[f].Emission[2] );
  825.          params[3] = FLOAT_TO_INT( CC.Light.Material[f].Emission[3] );
  826.      break;
  827.       case GL_SHININESS:
  828.          *params = ROUND( CC.Light.Material[f].Shininess );
  829.      break;
  830.       case GL_COLOR_INDEXES:
  831.      params[0] = ROUND( CC.Light.Material[f].AmbientIndex );
  832.      params[1] = ROUND( CC.Light.Material[f].DiffuseIndex );
  833.      params[2] = ROUND( CC.Light.Material[f].SpecularIndex );
  834.      break;
  835.       default:
  836.          gl_error( GL_INVALID_ENUM, "glGetMaterialfv(pname)" );
  837.    }
  838. }
  839.  
  840.  
  841.  
  842.  
  843. /*
  844.  * Notes:
  845.  *   When two-sided lighting is enabled we compute the color (or index)
  846.  *   for both the front and back side of the primitive.  Then, when the
  847.  *   orientation of the facet is later learned, we can determine which
  848.  *   color (or index) to use for rendering.
  849.  */
  850.  
  851.  
  852.  
  853. /* TODO:
  854.  * Store color indexes as GLfloats instead of GLuints?
  855.  */
  856.  
  857.  
  858.  
  859. /*
  860.  * Use current lighting/material settings to compute the RGBA color of
  861.  * a vertex.
  862.  * Input:  vertex - vertex position in eye coordinates
  863.  *         normal - surface normal vector
  864.  *         twoside - 0 = front face shading only, 1 = two-sided lighting
  865.  * Output:  frontcolor - resulting front-face color
  866.  *          backcolor - resulting back-face color
  867.  */
  868. void gl_color_shade( const GLfloat vertex[4],
  869.              const GLfloat normal[3],
  870.              GLuint twoside,
  871.                      GLfloat frontcolor[4],
  872.              GLfloat backcolor[4] )
  873. {
  874.    GLfloat R, G, B, A;
  875.    GLfloat norm[3];
  876.    GLint side, i;
  877.  
  878.    for (side=0;side<=twoside;side++) {
  879.       if (side==0) {
  880.          /* shade frontside */
  881.          norm[0] = normal[0];
  882.          norm[1] = normal[1];
  883.          norm[2] = normal[2];
  884.       }
  885.       else {
  886.          /* shade backside */
  887.          norm[0] = -normal[0];
  888.          norm[1] = -normal[1];
  889.          norm[2] = -normal[2];
  890.       }
  891.  
  892.       /* Compute color from global lighting: */
  893.       R = CC.Light.Material[side].Emission[0]
  894.         + CC.Light.Model.Ambient[0] * CC.Light.Material[side].Ambient[0];
  895.       G = CC.Light.Material[side].Emission[1]
  896.         + CC.Light.Model.Ambient[1] * CC.Light.Material[side].Ambient[1];
  897.       B = CC.Light.Material[side].Emission[2]
  898.         + CC.Light.Model.Ambient[2] * CC.Light.Material[side].Ambient[2];
  899.       A = CC.Light.Material[side].Diffuse[3];
  900.  
  901.       /* Add contribution from each light source */
  902.       for (i=0;i<=CC.Light.LastEnabled;i++) {
  903.  
  904.          if (CC.Light.Light[i].Enabled) {
  905.             GLfloat attenuation;
  906.             GLfloat ambientR, ambientG, ambientB;
  907.             GLfloat l[3];  /* unit vector from vertex to light */
  908.             GLfloat l_dot_norm;  /* dot product of l and norm */
  909.             GLfloat t;
  910.  
  911.             /* compute l, d, and attenuation */
  912.         if (CC.Light.Light[i].Position[3]==0.0) {
  913.            /* directional light */
  914.            /* Effectively, l is a vector from the origin to the light. */
  915.            l[0] = CC.Light.Light[i].NormPosition[0];
  916.            l[1] = CC.Light.Light[i].NormPosition[1];
  917.            l[2] = CC.Light.Light[i].NormPosition[2];
  918.                attenuation = 1.0F;
  919.         }
  920.         else {
  921.            /* positional light */
  922.                GLfloat d;     /* distance from vertex to light */
  923.            l[0] = CC.Light.Light[i].Position[0] - vertex[0];
  924.            l[1] = CC.Light.Light[i].Position[1] - vertex[1];
  925.            l[2] = CC.Light.Light[i].Position[2] - vertex[2];
  926.                d = (GLfloat) sqrt( l[0]*l[0] + l[1]*l[1] + l[2]*l[2] );
  927.                if (d>0.001) {
  928.                   GLfloat invd = 1.0F / d;
  929.                   l[0] *= invd;
  930.                   l[1] *= invd;
  931.                   l[2] *= invd;
  932.                }
  933.                attenuation = 1.0F / (CC.Light.Light[i].ConstantAttenuation
  934.                                 + d * (CC.Light.Light[i].LinearAttenuation
  935.                                 + d * CC.Light.Light[i].QuadraticAttenuation));
  936.             }
  937.  
  938.             /* ambient term */
  939.             ambientR = CC.Light.Light[i].Ambient[0]
  940.                      * CC.Light.Material[side].Ambient[0];
  941.             ambientG = CC.Light.Light[i].Ambient[1]
  942.                      * CC.Light.Material[side].Ambient[1];
  943.             ambientB = CC.Light.Light[i].Ambient[2]
  944.                      * CC.Light.Material[side].Ambient[2];
  945.  
  946.             l_dot_norm = DOT3( l, norm );
  947.  
  948.             /* diffuse and specular terms */
  949.             if (l_dot_norm<=0.0F) {
  950.                /* surface faces away from light */
  951.                R += attenuation * ambientR;
  952.                G += attenuation * ambientG;
  953.                B += attenuation * ambientB;
  954.                /* done with this light */
  955.             }
  956.             else {
  957.                GLfloat s[3], dot, spotlight_effect;
  958.                GLfloat diffuseR, diffuseG, diffuseB;
  959.                GLfloat specularR, specularG, specularB;
  960.  
  961.                /* spotlight factor */
  962.                if (CC.Light.Light[i].SpotCutoff==180.0F) {
  963.                   /* not a spot light */
  964.                   spotlight_effect = 1.0F;
  965.                }
  966.                else {
  967.                   GLfloat v[3], dot;
  968.                   v[0] = -l[0];  /* v points from light to vertex */
  969.                   v[1] = -l[1];
  970.                   v[2] = -l[2];
  971.                   dot = DOT3( v, CC.Light.Light[i].Direction );
  972.                   if (dot<=0.0F || acos(dot)*RAD2DEG > CC.Light.Light[i].SpotCutoff) {
  973.                      /* outside of cone */
  974.                      spotlight_effect = 0.0F;
  975.                   }
  976.                   else {
  977.                      spotlight_effect = pow( dot, CC.Light.Light[i].SpotExponent );
  978.                   }
  979.                }
  980.  
  981.                /* diffuse term */
  982.                diffuseR = l_dot_norm * CC.Light.Light[i].Diffuse[0]
  983.                   * CC.Light.Material[side].Diffuse[0];
  984.                diffuseG = l_dot_norm * CC.Light.Light[i].Diffuse[1]
  985.                 * CC.Light.Material[side].Diffuse[1];
  986.                diffuseB = l_dot_norm * CC.Light.Light[i].Diffuse[2]
  987.                 * CC.Light.Material[side].Diffuse[2];
  988.  
  989.                /* specular term */
  990.                if (CC.Light.Model.LocalViewer) {
  991.           GLfloat v[3];
  992.           v[0] = vertex[0];
  993.           v[1] = vertex[1];
  994.           v[2] = vertex[2];
  995.           NORMALIZE_3V( v );
  996.                   s[0] = l[0] - v[0];
  997.                   s[1] = l[1] - v[1];
  998.                   s[2] = l[2] - v[2];
  999.                }
  1000.                else {
  1001.                   s[0] = l[0];
  1002.                   s[1] = l[1];
  1003.                   s[2] = l[2] + 1.0F;
  1004.                }
  1005.                /* attention: s is not normalized, will be done, if necessary */
  1006.                dot = DOT3(s,norm);
  1007.  
  1008.            if (dot<=0.0) {
  1009.                   specularR = 0.0F;
  1010.                   specularG = 0.0F;
  1011.                   specularB = 0.0F;
  1012.            }
  1013.            else {
  1014.           GLdouble p;
  1015.                   /* now `correct' the dot product */
  1016.                   dot = dot / sqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2]);
  1017.           /* must be careful of underflow here! */
  1018.           p = pow( dot, (double) CC.Light.Material[side].Shininess );
  1019.           if (p<1.0e-35) {
  1020.                      specularR = 0.0F;
  1021.                      specularG = 0.0F;
  1022.                      specularB = 0.0F;
  1023.           }
  1024.           else {
  1025.              GLfloat spec_coef = (GLfloat) p;
  1026.                      specularR = spec_coef * CC.Light.Light[i].Specular[0]
  1027.                                  * CC.Light.Material[side].Specular[0];
  1028.                      specularG = spec_coef * CC.Light.Light[i].Specular[1]
  1029.                                  * CC.Light.Material[side].Specular[1];
  1030.                      specularB = spec_coef * CC.Light.Light[i].Specular[2]
  1031.                                  * CC.Light.Material[side].Specular[2];
  1032.           }
  1033.            }
  1034.  
  1035.                /* accumlate light[i]'s contribution to final color */
  1036.                t = attenuation * spotlight_effect;
  1037.                R += t * (ambientR + diffuseR + specularR);
  1038.                G += t * (ambientG + diffuseG + specularG);
  1039.                B += t * (ambientB + diffuseB + specularB);
  1040.             }
  1041.  
  1042.          } /*if*/
  1043.  
  1044.       } /*for*/
  1045.  
  1046.       if (side==0) {
  1047.          frontcolor[0] = CLAMP( R, 0.0F, 1.0F );
  1048.          frontcolor[1] = CLAMP( G, 0.0F, 1.0F );
  1049.          frontcolor[2] = CLAMP( B, 0.0F, 1.0F );
  1050.          frontcolor[3] = CLAMP( A, 0.0F, 1.0F );
  1051.       }
  1052.       else {
  1053.          backcolor[0] = CLAMP( R, 0.0F, 1.0F );
  1054.          backcolor[1] = CLAMP( G, 0.0F, 1.0F );
  1055.          backcolor[2] = CLAMP( B, 0.0F, 1.0F );
  1056.          backcolor[3] = CLAMP( A, 0.0F, 1.0F );
  1057.       }
  1058.  
  1059.    } /*for side*/
  1060. }
  1061.  
  1062.  
  1063.  
  1064.  
  1065. /*
  1066.  * Use current lighting/material settings to compute the RGBA colors of
  1067.  * an array of vertexes.
  1068.  * Input:  n - number of vertexes to process
  1069.  *         vertex - array of vertex positions in eye coordinates
  1070.  *         normal - array of surface normal vectors
  1071.  *         twoside - 0 = front face shading only, 1 = two-sided lighting
  1072.  * Output:  frontcolor - array of resulting front-face colors
  1073.  *          backcolor - array of resulting back-face colors
  1074.  */
  1075. void gl_color_shade_vertices( GLuint n,
  1076.                               GLfloat vertex[][4],
  1077.                               GLfloat normal[][3],
  1078.                               GLuint twoside,
  1079.                               GLfloat frontcolor[][4],
  1080.                               GLfloat backcolor[][4] )
  1081. {
  1082.    GLint side, i, j;
  1083.  
  1084.    for (side=0;side<=twoside;side++) {
  1085.       GLfloat ambient[MAX_LIGHTS][3];
  1086.  
  1087.       /*** Compute color contribution from global lighting ***/
  1088.       GLfloat r0, g0, b0, a0;
  1089.       r0 = CC.Light.Material[side].Emission[0]
  1090.          + CC.Light.Model.Ambient[0] * CC.Light.Material[side].Ambient[0];
  1091.       g0 = CC.Light.Material[side].Emission[1]
  1092.          + CC.Light.Model.Ambient[1] * CC.Light.Material[side].Ambient[1];
  1093.       b0 = CC.Light.Material[side].Emission[2]
  1094.          + CC.Light.Model.Ambient[2] * CC.Light.Material[side].Ambient[2];
  1095.       a0 = CC.Light.Material[side].Diffuse[3];
  1096.  
  1097.  
  1098.       /* Compute ambient color from each light.  Same for all vertices. */
  1099.       for (i=0;i<=CC.Light.LastEnabled;i++) {
  1100.          ambient[i][0] = CC.Light.Light[i].Ambient[0]
  1101.                        * CC.Light.Material[side].Ambient[0];
  1102.          ambient[i][1] = CC.Light.Light[i].Ambient[1]
  1103.                        * CC.Light.Material[side].Ambient[1];
  1104.          ambient[i][2] = CC.Light.Light[i].Ambient[2]
  1105.                        * CC.Light.Material[side].Ambient[2];
  1106.       }
  1107.  
  1108.  
  1109.       for (j=0;j<n;j++) {
  1110.          GLfloat R, G, B, A;
  1111.          GLfloat norm[3];
  1112.  
  1113.          if (side==0) {
  1114.             /* shade frontside */
  1115.             norm[0] = normal[j][0];
  1116.             norm[1] = normal[j][1];
  1117.             norm[2] = normal[j][2];
  1118.          }
  1119.          else {
  1120.             /* shade backside */
  1121.             norm[0] = -normal[j][0];
  1122.             norm[1] = -normal[j][1];
  1123.             norm[2] = -normal[j][2];
  1124.          }
  1125.  
  1126.          R = r0;
  1127.          G = g0;
  1128.          B = b0;
  1129.          A = a0;
  1130.  
  1131.          /* Add contribution from each light source */
  1132.          for (i=0;i<=CC.Light.LastEnabled;i++) {
  1133.  
  1134.             if (CC.Light.Light[i].Enabled) {
  1135.                GLfloat attenuation;
  1136.                GLfloat l[3];  /* unit vector from vertex to light */
  1137.                GLfloat l_dot_norm;  /* dot product of l and norm */
  1138.  
  1139.                /* compute l and attenuation */
  1140.                if (CC.Light.Light[i].Position[3]==0.0) {
  1141.                   /* directional light */
  1142.                   /* Effectively, l is a vector from the origin to the light */
  1143.                   l[0] = CC.Light.Light[i].NormPosition[0];
  1144.                   l[1] = CC.Light.Light[i].NormPosition[1];
  1145.                   l[2] = CC.Light.Light[i].NormPosition[2];
  1146.                   attenuation = 1.0F;
  1147.                }
  1148.                else {
  1149.                   /* positional light */
  1150.                   GLfloat d;     /* distance from vertex to light */
  1151.                   l[0] = CC.Light.Light[i].Position[0] - vertex[j][0];
  1152.                   l[1] = CC.Light.Light[i].Position[1] - vertex[j][1];
  1153.                   l[2] = CC.Light.Light[i].Position[2] - vertex[j][2];
  1154.                   d = (GLfloat) sqrt( l[0]*l[0] + l[1]*l[1] + l[2]*l[2] );
  1155.                   if (d>0.001F) {
  1156.                      GLfloat invd = 1.0F / d;
  1157.                      l[0] *= invd;
  1158.                      l[1] *= invd;
  1159.                      l[2] *= invd;
  1160.                   }
  1161.                   attenuation = 1.0F / (CC.Light.Light[i].ConstantAttenuation
  1162.                               + d * (CC.Light.Light[i].LinearAttenuation
  1163.                               + d * CC.Light.Light[i].QuadraticAttenuation));
  1164.                }
  1165.  
  1166.                l_dot_norm = DOT3( l, norm );
  1167.  
  1168.                /* diffuse and specular terms */
  1169.                if (l_dot_norm<=0.0F) {
  1170.                   /* surface faces away from light, no diffuse or specular */
  1171.                   R += attenuation * ambient[i][0];
  1172.                   G += attenuation * ambient[i][1];
  1173.                   B += attenuation * ambient[i][2];
  1174.                   /* done with this light */
  1175.                }
  1176.                else {
  1177.                   GLfloat s[3], dot, t, spotlight_effect;
  1178.                   GLfloat diffuseR, diffuseG, diffuseB;
  1179.                   GLfloat specularR, specularG, specularB;
  1180.                   
  1181.                   /* spotlight factor */
  1182.                   if (CC.Light.Light[i].SpotCutoff==180.0F) {
  1183.                      /* not a spot light */
  1184.                      spotlight_effect = 1.0F;
  1185.                   }
  1186.                   else {
  1187.                      GLfloat v[3], dot;
  1188.                      v[0] = -l[0];  /* v points from light to vertex */
  1189.                      v[1] = -l[1];
  1190.                      v[2] = -l[2];
  1191.                      dot = DOT3( v, CC.Light.Light[i].Direction );
  1192.                      if (dot<=0.0F || acos(dot)*RAD2DEG > CC.Light.Light[i].SpotCutoff) {
  1193.                         /* outside of cone */
  1194.                         spotlight_effect = 0.0F;
  1195.                      }
  1196.                      else {
  1197.                         spotlight_effect = pow( dot, CC.Light.Light[i].SpotExponent );
  1198.                      }
  1199.                   }
  1200.  
  1201.                   /* diffuse term */
  1202.                   diffuseR = l_dot_norm * CC.Light.Light[i].Diffuse[0]
  1203.                                * CC.Light.Material[side].Diffuse[0];
  1204.                   diffuseG = l_dot_norm * CC.Light.Light[i].Diffuse[1]
  1205.                                * CC.Light.Material[side].Diffuse[1];
  1206.                   diffuseB = l_dot_norm * CC.Light.Light[i].Diffuse[2]
  1207.                                * CC.Light.Material[side].Diffuse[2];
  1208.  
  1209.                   /* specular term */
  1210.                   if (CC.Light.Model.LocalViewer) {
  1211.                      GLfloat v[3];
  1212.                      v[0] = vertex[j][0];
  1213.                      v[1] = vertex[j][1];
  1214.                      v[2] = vertex[j][2];
  1215.                      NORMALIZE_3V( v );
  1216.                      s[0] = l[0] - v[0];
  1217.                      s[1] = l[1] - v[1];
  1218.                      s[2] = l[2] - v[2];
  1219.                   }
  1220.                   else {
  1221.                      s[0] = l[0];
  1222.                      s[1] = l[1];
  1223.                      s[2] = l[2] + 1.0F;
  1224.                   }
  1225.                   /* attention: s is not normalized, done later if needed */
  1226.                   dot = DOT3(s,norm);
  1227.  
  1228.                   if (dot<=0.0) {
  1229.                      specularR = 0.0F;
  1230.                      specularG = 0.0F;
  1231.                      specularB = 0.0F;
  1232.                   }
  1233.                   else {
  1234.                      GLdouble p;
  1235.                      /* now `correct' the dot product */
  1236.                      dot = dot / sqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2]);
  1237.                      /* must be careful of underflow here! */
  1238.                      p = pow( dot, (double)CC.Light.Material[side].Shininess );
  1239.                      if (p<1.0e-35) {
  1240.                         specularR = 0.0F;
  1241.                         specularG = 0.0F;
  1242.                         specularB = 0.0F;
  1243.                      }
  1244.                      else {
  1245.                         GLfloat spec_coef = (GLfloat) p;
  1246.                         specularR = spec_coef * CC.Light.Light[i].Specular[0]
  1247.                                     * CC.Light.Material[side].Specular[0];
  1248.                         specularG = spec_coef * CC.Light.Light[i].Specular[1]
  1249.                                     * CC.Light.Material[side].Specular[1];
  1250.                         specularB = spec_coef * CC.Light.Light[i].Specular[2]
  1251.                                     * CC.Light.Material[side].Specular[2];
  1252.                      }
  1253.                   }
  1254.                   t = attenuation * spotlight_effect;
  1255.                   R += t * (ambient[i][0] + diffuseR + specularR);
  1256.                   G += t * (ambient[i][1] + diffuseG + specularG);
  1257.                   B += t * (ambient[i][2] + diffuseB + specularB);
  1258.                }
  1259.  
  1260.             } /*if*/
  1261.  
  1262.          } /*for loop over lights*/
  1263.  
  1264.          if (side==0) {
  1265.             frontcolor[j][0] = CLAMP( R, 0.0F, 1.0F );
  1266.             frontcolor[j][1] = CLAMP( G, 0.0F, 1.0F );
  1267.             frontcolor[j][2] = CLAMP( B, 0.0F, 1.0F );
  1268.             frontcolor[j][3] = CLAMP( A, 0.0F, 1.0F );
  1269.          }
  1270.          else {
  1271.             backcolor[j][0] = CLAMP( R, 0.0F, 1.0F );
  1272.             backcolor[j][1] = CLAMP( G, 0.0F, 1.0F );
  1273.             backcolor[j][2] = CLAMP( B, 0.0F, 1.0F );
  1274.             backcolor[j][3] = CLAMP( A, 0.0F, 1.0F );
  1275.          }
  1276.       } /*loop over vertices*/
  1277.  
  1278.    } /*for side*/
  1279. }
  1280.  
  1281.  
  1282.  
  1283.  
  1284. /*
  1285.  * Use current lighting/material settings to compute the color index of
  1286.  * a vertex.
  1287.  * Input:  vertex - vertex position in viewing coordinates
  1288.  *         normal - surface normal vector
  1289.  *         twoside - 0 = front face shading only, 1 = two-sided lighting
  1290.  * Output:  frontindex - resulting front-face color index
  1291.  *          backindex - resulting back-face color index
  1292.  */
  1293. void gl_index_shade( const GLfloat vertex[4],
  1294.              const GLfloat normal[4],
  1295.              GLuint twoside,
  1296.              GLfloat *frontindex,
  1297.              GLfloat *backindex )
  1298. {
  1299.    GLfloat d_ci, s_ci;
  1300.    GLfloat diffuse, specular;  /* accumulated diffuse and specular terms */
  1301.    GLfloat d_a, s_a, index;
  1302.    GLfloat norm[3];
  1303.    GLint side, i;
  1304.  
  1305.    for (side=0;side<=twoside;side++) {
  1306.  
  1307.       if (side==0) {
  1308.          /* shade frontside */
  1309.          norm[0] = normal[0];
  1310.          norm[1] = normal[1];
  1311.          norm[2] = normal[2];
  1312.       }
  1313.       else {
  1314.          /* shade backside */
  1315.          norm[0] = -normal[0];
  1316.          norm[1] = -normal[1];
  1317.          norm[2] = -normal[2];
  1318.       }
  1319.  
  1320.       diffuse = specular = 0.0;
  1321.  
  1322.       /* Accumulate diffuse and specular from each light source */
  1323.       for (i=0;i<=CC.Light.LastEnabled;i++) {
  1324.  
  1325.          if (CC.Light.Light[i].Enabled) {
  1326.             GLfloat attenuation;
  1327.             GLfloat spotlight_effect;
  1328.             GLfloat l[3];  /* unit vector from vertex to light */
  1329.             GLfloat l_dot_norm;  /* dot product of l and norm */
  1330.  
  1331.             /* compute l and  attenuation */
  1332.         if (CC.Light.Light[i].Position[3]==0.0) {
  1333.            /* directional light */
  1334.            /* Effectively, l is a vector from the origin to the light. */
  1335.            l[0] = CC.Light.Light[i].NormPosition[0];
  1336.            l[1] = CC.Light.Light[i].NormPosition[1];
  1337.            l[2] = CC.Light.Light[i].NormPosition[2];
  1338.                attenuation = 1.0F;
  1339.         }
  1340.         else {
  1341.            /* positional light */
  1342.                GLfloat d;     /* distance from vertex to light */
  1343.            l[0] = CC.Light.Light[i].Position[0] - vertex[0];
  1344.            l[1] = CC.Light.Light[i].Position[1] - vertex[1];
  1345.            l[2] = CC.Light.Light[i].Position[2] - vertex[2];
  1346.                d = (GLfloat) sqrt( l[0]*l[0] + l[1]*l[1] + l[2]*l[2] );
  1347.                if (d>0.001) {
  1348.                   GLfloat invd = 1.0F / d;
  1349.                   l[0] *= invd;
  1350.                   l[1] *= invd;
  1351.                   l[2] *= invd;
  1352.                }
  1353.                attenuation = 1.0F / (CC.Light.Light[i].ConstantAttenuation
  1354.                                      + d * (CC.Light.Light[i].LinearAttenuation
  1355.                                      + d * CC.Light.Light[i].QuadraticAttenuation));
  1356.         }
  1357.  
  1358.             l_dot_norm = DOT3( l, norm );
  1359.  
  1360.             if (l_dot_norm>0.0F) {
  1361.  
  1362.                /* spotlight factor */
  1363.                if (CC.Light.Light[i].SpotCutoff==180.0F) {
  1364.                   /* not a spot light */
  1365.                   spotlight_effect = 1.0F;
  1366.                }
  1367.                else {
  1368.                   GLfloat v[3], dot;
  1369.                   v[0] = -l[0];  /* v points from light to vertex */
  1370.                   v[1] = -l[1];
  1371.                   v[2] = -l[2];
  1372.                   dot = DOT3( v, CC.Light.Light[i].Direction );
  1373.                   if (dot<=0.0F || acos(dot)*RAD2DEG > CC.Light.Light[i].SpotCutoff) {
  1374.                      /* outside of cone */
  1375.              spotlight_effect = 0.0F;
  1376.                   }
  1377.                   else {
  1378.                      spotlight_effect = pow( dot, CC.Light.Light[i].SpotExponent );
  1379.                   }
  1380.                }
  1381.  
  1382.                /* accumulate diffuse term */
  1383.                d_ci = 0.30F * CC.Light.Light[i].Diffuse[0]
  1384.                     + 0.59F * CC.Light.Light[i].Diffuse[1]
  1385.                     + 0.11F * CC.Light.Light[i].Diffuse[2];
  1386.                diffuse += l_dot_norm * d_ci * spotlight_effect * attenuation;
  1387.  
  1388.                /* accumulate specular term */
  1389.                {
  1390.                   GLfloat s[3], dot, spec_coef;
  1391.  
  1392.                   /* specular term */
  1393.                   if (CC.Light.Model.LocalViewer) {
  1394.              GLfloat v[3];
  1395.              v[0] = vertex[0];
  1396.              v[1] = vertex[1];
  1397.              v[2] = vertex[2];
  1398.              NORMALIZE_3V( v );
  1399.                      s[0] = l[0] - v[0];
  1400.                      s[1] = l[1] - v[1];
  1401.                      s[2] = l[2] - v[2];
  1402.                   }
  1403.                   else {
  1404.                      s[0] = l[0];
  1405.                      s[1] = l[1];
  1406.                      s[2] = l[2] + 1.0F;
  1407.                   }
  1408.                   /* attention: s is not normalized, will be done, if necessary */
  1409.                   dot = DOT3(s,norm);
  1410.  
  1411.           if (dot<=0.0F) {
  1412.              spec_coef = 0.0;
  1413.           }
  1414.           else {
  1415.              GLdouble p;
  1416.                      /* now `correct' the dot product */
  1417.                      dot = dot / sqrt(s[0]*s[0]+s[1]*s[1]+s[2]*s[2]);
  1418.              /* must be careful of underflow here! */
  1419.              p = pow( dot, (double)CC.Light.Material[side].Shininess );
  1420.              if (p<1.0e-35) {
  1421.             spec_coef = 0.0;
  1422.              }
  1423.              else {
  1424.             spec_coef = (GLfloat) p;
  1425.              }
  1426.           }
  1427.  
  1428.                   s_ci = 0.30F * CC.Light.Light[i].Specular[0]
  1429.                        + 0.59F * CC.Light.Light[i].Specular[1]
  1430.                        + 0.11F * CC.Light.Light[i].Specular[2];
  1431.                   specular += spec_coef * s_ci * spotlight_effect * attenuation;
  1432.               }
  1433.             }
  1434.  
  1435.          } /* if */
  1436.  
  1437.       } /* for */
  1438.  
  1439.       /* Now compute color index */
  1440.  
  1441.       if (specular>1.0F)
  1442.          specular = 1.0F;
  1443.  
  1444.       if (CC.Color.DitherFlag) {
  1445.      /* add one to index because dithering randomly subtracts one */
  1446.      d_a = CC.Light.Material[side].DiffuseIndex
  1447.            - CC.Light.Material[side].AmbientIndex - 1;
  1448.      s_a = CC.Light.Material[side].SpecularIndex
  1449.               - CC.Light.Material[side].AmbientIndex;
  1450.  
  1451.      index = CC.Light.Material[side].AmbientIndex + 1
  1452.              + diffuse * (1.0-specular) * d_a
  1453.                  + specular * s_a;
  1454.       }
  1455.       else {
  1456.      d_a = CC.Light.Material[side].DiffuseIndex
  1457.            - CC.Light.Material[side].AmbientIndex;
  1458.      s_a = CC.Light.Material[side].SpecularIndex
  1459.               - CC.Light.Material[side].AmbientIndex;
  1460.  
  1461.      index = CC.Light.Material[side].AmbientIndex
  1462.              + diffuse * (1.0-specular) * d_a
  1463.                  + specular * s_a;
  1464.       }
  1465.  
  1466.       if (index>CC.Light.Material[side].SpecularIndex) {
  1467.          index = CC.Light.Material[side].SpecularIndex;
  1468.       }
  1469.  
  1470.       if (side==0) {
  1471.      *frontindex = index;
  1472.       }
  1473.       else {
  1474.          *backindex = index;
  1475.       }
  1476.  
  1477.    } /*for side*/
  1478. }
  1479.  
  1480.